home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / mus / play / sparctracker100.lha / SparcTracker / str.c < prev   
C/C++ Source or Header  |  1992-10-28  |  15KB  |  517 lines

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /* str.c  -  plays sound/noisetracker files on a SparcStation                */
  4. /*                                                                           */
  5. /* Author   : Liam Corner - zenith@dcs.warwick.ac.uk                         */
  6. /*                                                                           */
  7. /* Usage    : str <filename>                                                 */
  8. /*            [f|z]cat filename | str                                        */
  9. /*                                                                           */
  10. /* ------------------------------------------------------------------------- */
  11. /*                                                                           */
  12. /* New Features added by Rochus Wessels - srb103@math.uni-muenster.de        */
  13. /* Version  : 1.00r - 28 Oct 1992                                            */
  14. /*                                                                           */
  15. /* 27 Oct 92: -v Option added                                                */
  16. /* 28 Oct 92: automatically decrunch .Z-Files                                */
  17. /*            additional Options -d,-h                                       */
  18. /*                                                                           */
  19. /*****************************************************************************/
  20.  
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <malloc.h>
  24.  
  25. #include <strings.h>
  26. #include <fcntl.h>
  27. #include "/usr/demo/SOUND/multimedia/libaudio.h"
  28. #include "/usr/demo/SOUND/multimedia/audio_device.h"
  29.  
  30.  
  31. /**********************************************************/
  32. /* uS is the number of uSeconds that a byte is played for */
  33. /* Sparc plays at 8000 bytes/sec  =>  1 byte = 125 uSec   */
  34. /* VSYNC is the number of bytes played in 1/50 sec        */
  35. /* ie 0.02/(uS * 10**-6)                                  */
  36. /**********************************************************/
  37. #define uS 125
  38. #define VSYNC 160
  39. #define AUDIO "/dev/audio"
  40.  
  41. #define MIN(A,B) ((A)<(B) ? (A) : (B))
  42. #define MAX(A,B) ((A)>(B) ? (A) : (B))
  43.  
  44.  
  45. typedef struct {    /***********************************/
  46.   char *info;       /* Sample                          */
  47.   int length;       /* Length of sample                */
  48.   float volume;     /* Fractional volume 0-1 (min-max) */
  49.   int rep_start;    /* Byte offset of repeat start     */
  50.   int rep_end;      /* Byte offset of repeat end       */
  51. } Voice;            /***********************************/
  52.  
  53.  
  54. typedef struct {                 /**************************/
  55.   char sample [64][4];           /* Sample number          */
  56.   char effect [64][4];           /* Effect number          */
  57.   unsigned char params [64][4];  /* Effect parameters      */
  58.   int period [64][4];            /* Period (pitch) of note */
  59. } Pattern;                       /**************************/
  60.  
  61.  
  62. typedef struct {         /***********************************************/
  63.   char old;              /* Sample number of last note                  */
  64.   char samp;             /* Sample number of current note               */
  65.   int pitch;             /* Current channel pitch (index to step_table) */
  66.   int slide;             /* Step size of pitch slide (if any)           */
  67.   unsigned int pointer;  /* Current sample position                     */
  68.   unsigned int step;     /* Sample offset increment (gives pitch)       */
  69.   float volume;          /* Fractional volume of current note           */
  70. } Channel;               /***********************************************/
  71.  
  72.  
  73. /*****************************************************************************/
  74. /* Skips the next 'n' input bytes - because fseek won't work on stdin        */
  75. /*****************************************************************************/
  76. void byteskip (fp, bytes)
  77. FILE *fp;
  78. int bytes;
  79. {
  80.   int loop;
  81.   for (loop=0; loop<bytes; loop++)
  82.     fgetc(fp);
  83. }
  84.  
  85.  
  86. /************************************************************************/
  87. /*      For routine 'cvt' only                                          */
  88. /************************************************************************/
  89. /*      Copyright 1989 by Rich Gopstein and Harris Corporation          */
  90. /************************************************************************/
  91.  
  92. unsigned int cvt(ch)
  93. int ch;
  94. {
  95.  
  96.   int mask;
  97.  
  98.   if (ch < 0) {
  99.     ch = -ch;
  100.     mask = 0x7f;
  101.   } else {
  102.     mask = 0xff;
  103.   }
  104.  
  105.   if (ch < 32) {
  106.     ch = 0xF0 | 15 - (ch / 2);
  107.   } else if (ch < 96) {
  108.     ch = 0xE0 | 15 - (ch - 32) / 4;
  109.   } else if (ch < 224) {
  110.     ch = 0xD0 | 15 - (ch - 96) / 8;
  111.   } else if (ch < 480) {
  112.     ch = 0xC0 | 15 - (ch - 224) / 16;
  113.   } else if (ch < 992) {
  114.     ch = 0xB0 | 15 - (ch - 480) / 32;
  115.   } else if (ch < 2016) {
  116.     ch = 0xA0 | 15 - (ch - 992) / 64;
  117.   } else if (ch < 4064) {
  118.     ch = 0x90 | 15 - (ch - 2016) / 128;
  119.   } else if (ch < 8160) {
  120.     ch = 0x80 | 15 - (ch - 4064) /  256;
  121.   } else {
  122.     ch = 0x80;
  123.   }
  124. return (mask & ch);
  125. }
  126.  
  127. void printusage(void)
  128. {
  129.   fprintf(stderr,"\nUsage: str [<filename>]\n"
  130.           "Options:\n"
  131.           "  -b patnr. : Starts at Pattern <patnr.> (0-63)\n"
  132.           "  -d        : Display Samplenames\n"
  133.           "  -h        : Display this Helppage\n"
  134.           "  -l        : Loop \n"
  135.           "  -r patnr  : Set Restart-Pattern <patnr.> (0-63)\n"
  136.           "  -s speed  : Set initial Speed <speed> (1-15)\n"
  137.           "  -v vol    : Set Volume <vol> (0-100)\n\n");
  138.   exit (1);
  139. }
  140.  
  141. int main (argc, argv)
  142. int argc;
  143. char **argv;
  144. {
  145.   FILE *fp, *audio;
  146.   int loop;
  147.   int notes, note, channel, vsync;
  148.   int pat, pat_num;
  149.   int byte, bytes;
  150.   int step_table [1024];
  151.   int speed=6;                      /* Default speed is 6 */
  152.   int end_pattern=0;
  153.   char songlength;
  154.   char tune [128];
  155.   char num_patterns=0;
  156.   unsigned char ulaw;
  157.   float dummy1,dummy2;
  158.   Voice voices [32];
  159.   Pattern patterns [64];
  160.   Channel ch [4];
  161.   
  162.   int argnum;
  163.   int ftype;
  164. #define FTYPE_FILE 0
  165. #define FTYPE_STDIN 1
  166. #define FTYPE_PIPE 2
  167. #define MAX_SLEN 512
  168.   char combuf[MAX_SLEN];
  169.   int opt_restart=0;
  170.   int opt_loop=0;
  171.   int opt_begin=0;
  172.   int opt_speed=-1;
  173.   int opt_display=0;
  174.  
  175. #if 0
  176.   if (argc>2)
  177.     {
  178.       fprintf(stderr,"Usage: str32 [<filename>]\n");
  179.       exit (1);
  180.     }
  181. #endif
  182.  
  183.   /***************************************************************************/
  184.   /* Creates a table of the byte_step << 16 for a given pitch                */
  185.   /* The step and pointer are stored << 16 to get accuracy without floats    */
  186.   /* eg to get double pitch only play every other byte                       */
  187.   /* so step of 0x10000 is normal pitch, 0x8000 is half, 0x20000 is double   */
  188.   /* Pointer is >> 16 when accessed, so 0x10000 is 1st byte, 0x20000 2nd etc */
  189.   /* I have no idea where the other numbers are from, I copied them from     */
  190.   /* a SoundTracker player for the Acorn Archimedes                          */
  191.   /***************************************************************************/
  192.   step_table[0]=0;
  193.   for (loop=1; loop<1024; loop++)
  194.     {
  195.       dummy1=3575872/loop;
  196.       dummy2=(dummy1/(1000000/uS))*60000;
  197.       step_table[loop]=(int)dummy2;
  198.     }
  199.  
  200.   {
  201.     double vol=1.0;
  202.     int Audio_fd=-1;
  203.     int err=0;
  204.     int intvol=0;
  205.     char option=0;
  206.     char  *Audio_dev = "/dev/audio";
  207.  
  208.     for (argnum=1;argnum<argc;argnum++)
  209.       {
  210.         if (argv[argnum][0]!='-')
  211.             break;
  212.         option=argv[argnum][1];
  213.         switch(option)
  214.           {
  215.           case 'b':
  216.           case 'r':
  217.           case 's':
  218.           case 'v':
  219.             if (argnum==argc)
  220.               {
  221.                 option=0;
  222.                 printusage();
  223.                 break;
  224.               }
  225.             argnum++;
  226.             sscanf(argv[argnum],"%d",&intvol);
  227.             break;
  228.           default:;
  229.           }
  230.         switch(option)
  231.           {
  232.           case 'b': opt_begin=intvol;
  233.             if (opt_begin<0 || opt_begin>63)
  234.               printusage();
  235.             break;
  236.           case 'd': opt_display=1;break;
  237.           case 'h': printusage();break;
  238.           case 'l': opt_loop=1;break;
  239.           case 'r': opt_restart=intvol;opt_loop=2;
  240.             if (opt_restart<0 || opt_restart>63)
  241.               printusage();
  242.             break;
  243.           case 's': opt_speed=intvol;
  244.             if (opt_speed<1 || opt_speed>15)
  245.               printusage();
  246.             speed=opt_speed;
  247.             break;
  248.           case 'v':
  249.             if (intvol<0 || intvol>100)
  250.               printusage();
  251.             Audio_fd = open(Audio_dev, O_WRONLY | O_NDELAY);
  252.             if (Audio_fd>=0)
  253.               {
  254.                 vol=(double)intvol/100.0;
  255.                 err=audio_set_play_gain(Audio_fd,&vol);
  256.                 close(Audio_fd);
  257.               }
  258.             break;
  259.           default:printusage();
  260.           }
  261.       }
  262.   }
  263.  
  264.   ftype=FTYPE_FILE;
  265.   if (argc==argnum)
  266.     {
  267.       fp=stdin;
  268.       ftype=FTYPE_STDIN;
  269.     }
  270.   else
  271.     {
  272. #define MAX_SLEN 512
  273.       int slen;
  274.       char * s;
  275.       char combuf[MAX_SLEN];
  276.  
  277.       s=argv[argnum];
  278.       slen=strlen(s);
  279.       
  280.       if (slen>=2 && slen<(MAX_SLEN-16))
  281.         {
  282.           if (s[slen-2]=='.' && s[slen-1]=='Z')
  283.             {
  284.               strcpy(combuf,"zcat ");
  285.               strcat(combuf,s);
  286.               ftype=FTYPE_PIPE;
  287.             }
  288.         }
  289.  
  290.       if (ftype==FTYPE_PIPE)
  291.         fp=popen(combuf,"r");
  292.       else
  293.         fp=fopen(argv[argnum],"r");
  294.     }
  295.   if (fp==NULL)
  296.     {
  297.       fprintf(stderr,"str: unable to open tune file %s\n",argv[1]);
  298.       exit (1);
  299.     }
  300.  
  301.  
  302.   if (opt_display)
  303.     {
  304.       char s[22];
  305.       int i;
  306.  
  307.       for (i=0;i<20;i++)
  308.         s[i]=fgetc(fp);
  309.       s[20]=0;
  310.       printf("Module: %s\n",s); 
  311.     }
  312.   else
  313.     byteskip(fp,20);          /* Skips over filename */
  314.  
  315.   
  316.   /* Reads in the 31 sample-information tables */
  317.   for (loop=1; loop<32; loop++)
  318.     {
  319.       if (opt_display)
  320.         {
  321.           char s[24];
  322.           int i;
  323.  
  324.           for (i=0;i<22;i++)
  325.             s[i]=fgetc(fp);
  326.           s[22]=0;
  327.           printf(" %2d: %s\n",loop,s); 
  328.         }
  329.       else
  330.         byteskip(fp,22);      /* Skips over sample name */
  331.       voices[loop].length=((fgetc(fp)<<8)|fgetc(fp))*2;
  332.       fgetc(fp);
  333.       voices[loop].volume=fgetc(fp);
  334.       voices[loop].volume=MIN(voices[loop].volume, 64);
  335.       voices[loop].volume/=64;   /* Volume is a fraction */
  336.       voices[loop].rep_start=((fgetc(fp)<<8)|fgetc(fp))*2;
  337.       voices[loop].rep_end=((fgetc(fp)<<8)|fgetc(fp))*2;
  338.       if (voices[loop].rep_end==2)
  339.     {
  340.       /* If there is no repeat then start and end */
  341.       /* are set to the end of the sample         */
  342.       voices[loop].rep_end=voices[loop].length;
  343.       voices[loop].rep_start=voices[loop].length;
  344.     }
  345.       else
  346.     {
  347.       /* If there is a repeat then end=start+length, but must be */
  348.       /* less than the sample length.  Not sure if this is 100%  */
  349.       /* correct, but it seems to work OK :-)                    */
  350.       voices[loop].rep_end+=voices[loop].rep_start;
  351.       voices[loop].rep_end=MIN(voices[loop].rep_end, voices[loop].length);
  352.     }
  353.     }
  354.   voices[0].length=0;
  355.  
  356.  
  357.   songlength=fgetc(fp);
  358.  
  359.  
  360.   byteskip(fp,1);
  361.  
  362.  
  363.   /* Reads in the tune */
  364.   for (loop=0; loop<128; loop++)
  365.     {
  366.       tune[loop]=fgetc(fp);
  367.       if (tune[loop]>num_patterns) num_patterns=tune[loop];
  368.     }
  369.   num_patterns++;
  370.  
  371.  
  372.   byteskip(fp,4);
  373.  
  374.  
  375.   for (pat_num=0; pat_num<num_patterns; pat_num++)  /* Reads in the patterns */
  376.     {
  377.       for (notes=0; notes<64; notes++)              /* 64 notes per pattern  */
  378.     {
  379.       for (channel=0; channel<4; channel++)     /* 4 channels per note   */
  380.         {
  381.           note=(fgetc(fp)<<24) | (fgetc(fp)<<16) | (fgetc(fp)<<8) | fgetc(fp);
  382.           (patterns[pat_num]).effect[notes][channel]=(note & 0xF00) >> 8;
  383.           (patterns[pat_num]).params[notes][channel]=note & 0xFF;
  384.           (patterns[pat_num]).sample[notes][channel]=((note & 0xF000)>>12) | ((note>>24) & 0x10);
  385.           (patterns[pat_num]).period[notes][channel]=MIN((note & 0xFFF0000) >> 16, 1023);
  386.         }
  387.     }
  388.     }
  389.  
  390.  
  391.  
  392.   /* Stores the samples voices as an array of char */
  393.   for (loop=1; loop<32; loop++)
  394.     {
  395.       voices[loop].info=malloc(voices[loop].length);
  396.       if (voices[loop].info==NULL)
  397.     {
  398.       fprintf(stderr, "str: unable to allocate memory\n");
  399.       exit (1);
  400.     }
  401.       fread(voices[loop].info, 1, voices[loop].length, fp);
  402.     }
  403.  
  404.   if (feof(fp))
  405.     {
  406.       fprintf(stderr,"str: input file may be corrupt\n");
  407. /*      exit (1);
  408. */    }
  409.  
  410.  
  411.   switch(ftype)
  412.     {
  413.     case FTYPE_FILE: fclose(fp); break;
  414.     case FTYPE_PIPE: pclose(fp); break;
  415.     default:;
  416.     }
  417.  
  418.   audio=fopen(AUDIO, "w");
  419.   if (audio==NULL)
  420.     {
  421.       fprintf(stderr,"str: unable to access %s\n",AUDIO);
  422.       exit (1);
  423.     }
  424.  
  425.   for (loop=0; loop<4; loop++)
  426.     {
  427.       ch[loop].old=0;
  428.       ch[loop].pointer=0;
  429.       ch[loop].step=0;
  430.       ch[loop].volume=0;
  431.       ch[loop].pitch=0;
  432.     }
  433.  
  434.  
  435.   do {
  436.   for (pat_num=opt_begin; pat_num<songlength; pat_num++)
  437.     {
  438.       pat=tune[pat_num];
  439.       for (notes=0; notes<64; notes++)
  440.     {
  441.       for (channel=0; channel<4; channel++)
  442.         {
  443.           ch[channel].samp=patterns[pat].sample[notes][channel];
  444.           if (!ch[channel].samp)              /* If sample number=0 */
  445.         ch[channel].samp=ch[channel].old; /* continue last note */
  446.           else
  447.         {
  448.           ch[channel].volume=voices[ch[channel].samp].volume;
  449.           ch[channel].pointer=0;
  450.           ch[channel].step=step_table[patterns[pat].period[notes][channel]];
  451.           ch[channel].pitch=patterns[pat].period[notes][channel];
  452.         }
  453.           ch[channel].old=ch[channel].samp;
  454.           ch[channel].slide=0;
  455.           switch (patterns[pat].effect[notes][channel])  /* Do effects */
  456.         {
  457.         case 0xF : speed=patterns[pat].params[notes][channel];
  458.           break;
  459.         case 0xD : end_pattern=1;
  460.           break;
  461.         case 0xC : ch[channel].volume=MIN((patterns[pat].params[notes][channel]),64);
  462.                    ch[channel].volume/=64;
  463.           break;
  464.         case 2   : ch[channel].slide=patterns[pat].params[notes][channel]-1;
  465.           break;
  466.         case 1   : ch[channel].slide=-patterns[pat].params[notes][channel]-1;
  467.           break;
  468.         case 0   : break;
  469.         default  : ;
  470.         }
  471.         }
  472.       if (end_pattern)     /* Skip to end of pattern if necessary */
  473.         {
  474.           notes=64;
  475.           end_pattern=0;
  476.         }
  477.       else
  478.         for (vsync=0; vsync<speed; vsync++)       /* 1 vsync = 0.02 sec */
  479.           {
  480.         for (bytes=0; bytes<VSYNC; bytes++)   /* 160*125uSec = 0.02 */
  481.           {
  482.             byte=0;
  483.             for (channel=0; channel<4; channel++)
  484.               {      
  485.             if ((ch[channel].pointer>>16) < voices[ch[channel].samp].rep_end)
  486.               {
  487.                 /* byte = sum of (sample byte * volume) for each */
  488.                 /* of 4 channels which mixes the sounds          */
  489.                 byte+=(int)((voices[ch[channel].samp].info[ch[channel].pointer>>16])*(ch[channel].volume));
  490.                 ch[channel].pointer+=ch[channel].step;
  491.               }
  492.             else
  493.               /* If at end of sample jump to rep_start position */
  494.               ch[channel].pointer=voices[ch[channel].samp].rep_start<<16;
  495.               }
  496.             ulaw=(unsigned char) cvt(byte*4);     /* Convert byte */
  497.             fputc(ulaw,audio);                /* and play the note */
  498.           }
  499.         for (channel=0; channel<4; channel++)   /* Do end of vsync */
  500.           if (ch[channel].slide)                /* effects         */
  501.             {
  502.               ch[channel].pitch+=ch[channel].slide;
  503.               ch[channel].pitch=MIN(ch[channel].pitch, 1023);
  504.               ch[channel].pitch=MAX(ch[channel].pitch, 0);
  505.               ch[channel].step=step_table[ch[channel].pitch];
  506.             } 
  507.           }
  508.     }
  509.     } /* for */
  510.   opt_begin=opt_restart;
  511.   } while (opt_loop);
  512.  
  513.   
  514.   fclose(audio);
  515.   return (0);
  516. }
  517.